// Common/Wildcard.h

#ifndef __COMMON_WILDCARD_H
#define __COMMON_WILDCARD_H

#include "Common/MyFixes.h"

#include <vector>
#include <memory>
#include <deque>

namespace Common
{

namespace FileSystem
{

int CompareFileNames(const CString &s1, const CString &s2);

void SplitPathToParts(const CString &path, CStringVector &pathParts);
void SplitPathToParts(const CString &path, CString &dirPrefix, CString &name);
CString ExtractDirPrefixFromPath(const CString &path);
CString ExtractFileNameFromPath(const CString &path);
bool DoesNameContainWildCard(const CString &path);
bool CompareWildCardWithName(const CString &mask, const CString &name);


namespace Wildcard {

struct CItem
{
  CStringVector PathParts;
  bool Recursive;
  bool ForFile;
  bool ForDir;
  bool CheckPath(const CStringVector &pathParts, bool isFile) const;
};

class CCensorNode
{
  CCensorNode *Parent;
  bool CheckPathCurrent(bool include, const CStringVector &pathParts, bool isFile) const;
  void AddItemSimple(bool include, std::shared_ptr<CItem> &item);
  bool CheckPath(CStringVector &pathParts, bool isFile, bool &include) const;
public:
	typedef std::vector<std::shared_ptr<CCensorNode> > SubNodeArrayType;
	typedef std::deque<std::shared_ptr<CItem> >			ItemArrayType;

  CCensorNode(): Parent(0) { };
  CCensorNode(const CString &name, CCensorNode *parent): Name(name), Parent(parent) { };
  CString Name;
  SubNodeArrayType SubNodes;
  ItemArrayType IncludeItems;
  ItemArrayType ExcludeItems;

  int FindSubNode(const CString &path) const;

  void AddItem(bool include, std::shared_ptr<CItem> &item);
  void AddItem(bool include, const CString &path, bool recursive, bool forFile, bool forDir);
  void AddItem2(bool include, const CString &path, bool recursive);

  bool NeedCheckSubDirs() const;
  bool AreThereIncludeItems() const;

  bool CheckPath(const CString &path, bool isFile, bool &include) const;
  bool CheckPath(const CString &path, bool isFile) const;

  bool CheckPathToRoot(bool include, CStringVector &pathParts, bool isFile) const;
  // bool CheckPathToRoot(const CString &path, bool isFile, bool include) const;
  void ExtendExclude(const std::shared_ptr<CCensorNode> &fromNodes);
};

struct CPair
{
  CString Prefix;
  std::shared_ptr<CCensorNode> Head;
  CPair(const CString &prefix): Prefix(prefix) 
  { Head = std::make_shared<CCensorNode>(); };
  CPair(const CPair & obj) : 
	  Prefix(obj.Prefix),
	  Head(obj.Head)
  {}
  CPair& operator=(const CPair & obj)
  {
		Prefix = obj.Prefix;
		Head = obj.Head;
  }
};

class CCensor
{
  int FindPrefix(const CString &prefix) const;
public:
	std::vector<CPair> Pairs;
  bool AllAreRelative() const
    { return (Pairs.size() == 1 && Pairs.front().Prefix.IsEmpty()); }
  void AddItem(bool include, const CString &path, bool recursive);
  bool CheckPath(const CString &path, bool isFile) const;
  void ExtendExclude();
};

}

}

}
#endif
